import type {
  ButtonProps,
  CheckboxOptionType,
  DatePickerProps,
  FormItemProps,
  FormProps,
  ImageProps,
  InputNumberProps,
  InputProps,
  RadioProps,
  SelectProps,
  TreeSelectProps,
  SwitchProps,
  UploadFile,
  GetProp
} from 'antd'
import type { RangePickerProps } from 'antd/es/date-picker'
import type { FormInstance, Rule } from 'antd/es/form'
import type { TextAreaProps } from 'antd/es/input'
import type { UploadChangeParam, UploadProps } from 'antd/es/upload'
import type { UploadListType } from 'antd/es/upload/interface'
import type { ReactNode } from 'react'

// 组件类型
export enum ElementType {
  BUTTON,
  INPUT,
  INPUTNUMBER,
  TEXTAREA,
  SELECT,
  RADIO,
  SWITCH,
  DATEPICKER,
  RANGEPICKER,
  UPLOAD,
  IMAGE,
  CUSTOM,
  TREESELECT
}

export interface IBaseFormExp {
  baseFormInstance: FormInstance<any>
}

export type Elements =
  | IButton
  | IInput
  | IInputNumber
  | ITextArea
  | ISelect
  | IRadio
  | ISwitch
  | IDatePicker
  | IRangePicker
  | IUpload
  | ISingleImage
  | IGroupImage
  | ICustom
  | ITreeSelect

export interface IBaseFormConfig {
  elements: Array<Elements> // 配置项
  layout?: 'inline' | 'horizontal' | 'vertical'
  initialValues?: Record<string, any> // 初始值
  formPorps?: FormProps // Form props
}
// formItem props
export interface IFormItem {
  key: string
  type: ElementType
  label: FormItemProps['label']
  formItemProps?: FormItemProps
  field: string // 对应 name
  rules?: Rule[]
}
// 按钮
export interface IButton extends Omit<IFormItem, 'field'> {
  type: ElementType.BUTTON
  disabled?: boolean
  noStyle?: boolean
  loading?: boolean
  onClick?: ButtonProps['onClick']
  props?: ButtonProps
}
export interface IInput extends IFormItem {
  type: ElementType.INPUT
  disabled?: boolean
  props?: InputProps
  onBlur?: InputProps['onBlur']
  onChange?: InputProps['onChange']
}
export interface IInputNumber extends IFormItem {
  type: ElementType.INPUTNUMBER
  disabled?: boolean
  min?: InputNumberProps['min']
  max?: InputNumberProps['max']
  addonAfter?: InputNumberProps['addonAfter']
  props?: InputNumberProps
  onBlur?: InputNumberProps['onBlur']
  onChange?: InputNumberProps['onChange']
}
export interface ITextArea extends IFormItem {
  type: ElementType.TEXTAREA
  disabled?: boolean
  props?: TextAreaProps
  onBlur?: TextAreaProps['onBlur']
  onChange?: TextAreaProps['onChange']
}
export interface ISelect extends IFormItem {
  type: ElementType.SELECT
  options: GetProp<SelectProps, 'options'>[number][] // SelectProps['options'];
  allowClear?: boolean
  disabled?: boolean
  props?: SelectProps
  onChange?: SelectProps['onChange']
}
export interface ITreeSelect extends IFormItem {
  type: ElementType.TREESELECT
  options: GetProp<TreeSelectProps, 'treeData'>[number][] // TreeSelectProps['treeData'];
  allowClear?: boolean
  disabled?: boolean
  props?: TreeSelectProps // antd select props
  onChange?: TreeSelectProps['onChange']
}
export interface IRadio extends IFormItem {
  type: ElementType.RADIO
  options: CheckboxOptionType[]
  disabled?: boolean
  props?: RadioProps
}
export interface ISwitch extends IFormItem {
  type: ElementType.SWITCH
  disabled?: boolean
  defaultChecked?: boolean
  onChange?: SwitchProps['onChange']
  props?: SwitchProps
}
export interface IDatePicker extends IFormItem {
  type: ElementType.DATEPICKER
  allowClear?: boolean
  props?: DatePickerProps
}
export interface IRangePicker extends IFormItem {
  type: ElementType.RANGEPICKER
  allowClear?: boolean
  props?: RangePickerProps
}

export interface IUpload extends IFormItem {
  type: ElementType.UPLOAD
  listType?: UploadListType
  accept?: UploadProps['accept']
  maxCount?: UploadProps['maxCount']
  multiple?: boolean
  onChange?: ((info: UploadChangeParam<UploadFile<any>>) => void) | undefined
  children?: ReactNode
  props?: UploadProps
}
export interface IImage extends IFormItem {
  type: ElementType.IMAGE
  props?: ImageProps
  group?: boolean
}
export interface ISingleImage extends IImage {
  group?: false
  src: string
}
export interface IGroupImage extends IImage {
  group: true
  items: string[]
}
export interface ICustom extends IFormItem {
  type: ElementType.CUSTOM
  noStyle?: boolean
  element: ReactNode
}
